﻿using Model;
using System;
using System.Collections.Generic;
using System.Timers;
using ME = Model.Environment;

namespace Interpreter
{
	public class Controller
	{
		private Timer timer;
		private StringInterpreter interpreter;
		private Persistence persistence;

		public bool Started
		{
			get { return timer != null && timer.Enabled; }
		}

		public Controller()
		{
			persistence = new Persistence();
			interpreter = new StringInterpreter();
			timer = new Timer();
			timer.Elapsed += timer_Elapsed;
		}

		public List<CellDefinition> LoadCellDefinitions(string filename)
		{
			ME.CellDefinitions = persistence.ParseCellDefinitions(filename);
			return GetCellDefinitionAsList();
		}

		public List<CellDefinition> GetCellDefinitionAsList()
		{
			List<CellDefinition> cellDefs = new List<CellDefinition>();

			foreach (CellDefinition tmpCD in ME.CellDefinitions.Values)
			{
				cellDefs.Add(tmpCD);
			}

			return cellDefs;
		}

		public string[] LoadRules(string filename)
		{
			return persistence.LoadRules(filename);
		}

		public void InterpreteRules(string[] rules)
		{
			interpreter.EvaluateRules(rules);
		}

		public Preferences LoadPreferences(string filename)
		{
			return persistence.ParsePreferences(filename);
		}

		/// <summary>
		/// Startet die Simulation
		/// </summary>
		/// <param name="field"></param>
		/// <param name="preferences"></param>
		public void StartSimulation()
		{
			if (!timer.Enabled)
			{
				DoStep();
				timer.Interval = ME.Preferences.ActualizationInterval;
				timer.Start();
			}
		}

		/// <summary>
		/// Führt einen Simulationsschritt durch
		/// </summary>
		/// <param name="field"></param>
		/// <param name="preferences"></param>
		public void CalculateStep()
		{
			if (!timer.Enabled)
			{
				DoStep();
			}
		}

		private void DoStep()
		{
			interpreter.CalculateStep();
			OnStepCalculated();
		}

		void timer_Elapsed(object sender, ElapsedEventArgs e)
		{
			DoStep();
		}

		public void PauseSimulation()
		{
			timer.Stop();
		}

		#region OnStepCalculated
		public delegate void StepCalculatedEventHandler(object sender, EventArgs e);

		public event StepCalculatedEventHandler StepCalculated;

		protected void OnStepCalculated()
		{
			if (StepCalculated != null)
			{
				EventArgs args = new EventArgs();
				StepCalculated(this, args);
			}
		}
		#endregion
	}
}
